On voit que les deux premières colonnes (X & id) sont inutiles pour nos analyses, on va donc les supprimer.
data <- read.csv("data/train.csv")
data <- data[!rowMeans(is.na(data)*1) > 0,] # On supprime les lignes ou il y a des valeurs manquantes
str(data)
## 'data.frame': 103594 obs. of 25 variables:
## $ X : int 0 1 2 3 4 5 6 7 8 9 ...
## $ id : int 70172 5047 110028 24026 119299 111157 82113 96462 79485 65725 ...
## $ Gender : chr "Male" "Male" "Female" "Female" ...
## $ Customer.Type : chr "Loyal Customer" "disloyal Customer" "Loyal Customer" "Loyal Customer" ...
## $ Age : int 13 25 26 25 61 26 47 52 41 20 ...
## $ Type.of.Travel : chr "Personal Travel" "Business travel" "Business travel" "Business travel" ...
## $ Class : chr "Eco Plus" "Business" "Business" "Business" ...
## $ Flight.Distance : int 460 235 1142 562 214 1180 1276 2035 853 1061 ...
## $ Inflight.wifi.service : int 3 3 2 2 3 3 2 4 1 3 ...
## $ Departure.Arrival.time.convenient: int 4 2 2 5 3 4 4 3 2 3 ...
## $ Ease.of.Online.booking : int 3 3 2 5 3 2 2 4 2 3 ...
## $ Gate.location : int 1 3 2 5 3 1 3 4 2 4 ...
## $ Food.and.drink : int 5 1 5 2 4 1 2 5 4 2 ...
## $ Online.boarding : int 3 3 5 2 5 2 2 5 3 3 ...
## $ Seat.comfort : int 5 1 5 2 5 1 2 5 3 3 ...
## $ Inflight.entertainment : int 5 1 5 2 3 1 2 5 1 2 ...
## $ On.board.service : int 4 1 4 2 3 3 3 5 1 2 ...
## $ Leg.room.service : int 3 5 3 5 4 4 3 5 2 3 ...
## $ Baggage.handling : int 4 3 4 3 4 4 4 5 1 4 ...
## $ Checkin.service : int 4 1 4 1 3 4 3 4 4 4 ...
## $ Inflight.service : int 5 4 4 4 3 4 5 5 1 3 ...
## $ Cleanliness : int 5 1 5 2 3 1 2 4 2 2 ...
## $ Departure.Delay.in.Minutes : int 25 1 0 11 0 0 9 4 0 0 ...
## $ Arrival.Delay.in.Minutes : num 18 6 0 9 0 0 23 0 0 0 ...
## $ satisfaction : chr "neutral or dissatisfied" "neutral or dissatisfied" "satisfied" "neutral or dissatisfied" ...
# On retire les colonnes inutiles
data <- data[,c(-1,-2)]
# On garde les 5000 premieres lignes
data <- data[1:5000,]
# On modifie les noms des lignes pour le style ;-)
row.names(data) <- paste("n°", sep="", 1:dim(data)[1])
# On renomme les colonnes pour avoir des noms moins longs (Utile pour l'affichage)
colnames(data) <- c("Genre", "Fidélité", "Age", "Type.du.vol", "Classe", "Distance", "Wifi", "Horaire.pratique", "Facilité.resevation", "Emplacement.porte", "Nourriture", "Enregistrement.en.ligne", "Siege.confort", "Loisir", "On.board.service", "Espace.jambe", "Gestion.bagage", "Checkin.service", "Inflight.service", "Propreté", "Retard.depart", "Retard.arrivé", "Satisfaction")
Petit avant gout des données :
paged_table(data)
par(fig=c(0,1/2,1/2,1))
pie(table(data$Genre), col = c("pink","blue"),cex=0.8)
par(fig=c(0,1/2,0,1/2),new=TRUE)
pie(table(data$Fidélité), col = c("red","green"),cex=0.8)
par(fig=c(1/2,1,1/2,1),new=TRUE)
pie(table(data$Type.du.vol), col = rainbow(2), cex=0.8)
par(fig=c(1/2,1,0,1/2),new=TRUE)
pie(table(data$Classe), col = rainbow(3),cex=0.8)
par(fig=c(1/3-1/5,2/3+1/5,1/3-1/5,2/3+1/5),new=TRUE)
pie(table(data$Satisfaction), col=c("red","green"), cex=0.8)
Les notes sont assez homogènes, elles ont toutes :
Un 1er quartile égal à 2 ou 3
Une médiane égal à 3 ou 4.
Un 3-ème quartile égale à 4 ou 5.
Les moyennes pour les notes vont de 2.74 à 3.65.
summary(data[,7:20])
## Wifi Horaire.pratique Facilité.resevation Emplacement.porte
## Min. :0.000 Min. :0.00 Min. :0.000 Min. :1.000
## 1st Qu.:2.000 1st Qu.:2.00 1st Qu.:2.000 1st Qu.:2.000
## Median :3.000 Median :3.00 Median :3.000 Median :3.000
## Mean :2.742 Mean :3.03 Mean :2.766 Mean :2.971
## 3rd Qu.:4.000 3rd Qu.:4.00 3rd Qu.:4.000 3rd Qu.:4.000
## Max. :5.000 Max. :5.00 Max. :5.000 Max. :5.000
## Nourriture Enregistrement.en.ligne Siege.confort Loisir
## Min. :0.000 Min. :0.000 Min. :1.000 Min. :0.000
## 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000
## Median :3.000 Median :3.000 Median :4.000 Median :4.000
## Mean :3.218 Mean :3.251 Mean :3.422 Mean :3.338
## 3rd Qu.:4.000 3rd Qu.:4.000 3rd Qu.:5.000 3rd Qu.:4.000
## Max. :5.000 Max. :5.000 Max. :5.000 Max. :5.000
## On.board.service Espace.jambe Gestion.bagage Checkin.service
## Min. :0.00 Min. :0.000 Min. :1.000 Min. :1.000
## 1st Qu.:2.00 1st Qu.:2.000 1st Qu.:3.000 1st Qu.:3.000
## Median :4.00 Median :4.000 Median :4.000 Median :3.000
## Mean :3.36 Mean :3.338 Mean :3.622 Mean :3.318
## 3rd Qu.:4.00 3rd Qu.:4.000 3rd Qu.:5.000 3rd Qu.:4.000
## Max. :5.00 Max. :5.000 Max. :5.000 Max. :5.000
## Inflight.service Propreté
## Min. :0.000 Min. :1.000
## 1st Qu.:3.000 1st Qu.:2.000
## Median :4.000 Median :3.000
## Mean :3.653 Mean :3.267
## 3rd Qu.:5.000 3rd Qu.:4.000
## Max. :5.000 Max. :5.000
On peut aussi observer les autres variables quantitatives :
par(mfrow=c(2,2))
boxplot(data$Age, main="Âge")
boxplot(data$Distance, main="Distance")
boxplot(data$Retard.depart, main="Retard depart")
boxplot(data$Retard.arrivé, main="Retard arrivée")
On récupère toutes les données quantitatives et la satisfaction.
On ne prend que les 5000 premières lignes car le data set est trop gros (+100 000 lignes)
# On récupère Âge/Distance du vol/Retard Depart/Retard Arrivé (colonne 3/6/21/22), les notes (colonnes 7 à 20) et la satisfaction (colonne 23)
data_bis <- data[,c(3,6,21,22,7:20,23)]
res <- PCA(data_bis, quanti.sup=1:4, quali.sup=19, graph=FALSE)
Il est évident de penser que les notes attribuées par les voyageurs influent sur leur satisfaction, on peut le voir avec le graphe ci- dessous. Pour ne pas attribuer trop d’importance aux moyennes donner par des individus, on associe un poids qui correspond à la taille du groupe pour chaque moyenne attribuée.
Ainsi, on va faire notre ACP sur les notes.
Les individus ou variables peuvent être proches dans le plan mais eloignés dans l’espace s’ils sont mal représentés dans le plan. Ainsi, il est important d’expliquer les individus avec des variables bien representées dans le plan. Pour cela on veillera à ne pas prendre les variables et individus ayant un cos2 trop bas. Ici on choisit un cos2 égale à 0.58 afin qu’il ne soit pas trop bas et qu’on ait au moins 4 variables à utiliser afin d’expliquer nos individus sur les axes 1 et 2.
Ici l’axe 1 va faire le contraste entre le confort à bord (droite) et l’inconfort (gauche), tandis que l’axe 2 fera le contraste entre les aspects techniques pour ce qui concerne le vol.
Les variables quantitatives supplémentaires ne sont pas du tout interprétables
plot(res,select="cos2 0.58", choix="varcor")
On peut voir une nette séparation entre les individus satisfaits et non satisfaits. Les individus satisfaits sont ceux s’étant amusé et ayant trouvé l’avion propre. À l’inverse les individus non satisfaits ont octroyé des notes plus basses concernant la propreté et les loisirs. On ne peut pas vraiment dire pour l’instant si la facilité de réservation et le wifi à bord influent sur la satisfaction du passager. Ici par exemple l’individu n°3297 est satisfait, or il a mal noté les loisirs, la propreté, le wifi et la facilité de réservation. Sa satisfaction est probablement influencé par d’autres variables, qui sont qualitatives. On se penchera sur ce sujet lors de l’ACM.
plot(res,habillage=19, select="cos2 0.8", choix="ind",cex = 0.6)
L’individu qui contribue le plus à l’axe 1 y contribue à 0.15%.
Il y a 40 individus qui y contribuent pour plus de 0.1%
On n’a pas d’individus atypiques, ce qui est normal car nos données sont des notes entre 0 et 5 et on a vu qu’elles étaient assez homogènes
max(res$ind$contrib[,1])
## [1] 0.1525821
sum((res$ind$contrib[,1] > 0.1)*1)
## [1] 40
On peut voir premièrement que les 3 premiers axes expliquent bien l’inertie sur les données. Les axes étant orthogonaux, les axes 1 et 2 prennent en compte 27.01% + 16.87% = 43.88% du jeu de données expliquent 44.56% de l’inertie. On peut aussi voir que l’axe 2 et 3 expliquent à peu près autant l’un que l’autre l’inertie, ainsi on pourra aussi visualiser les données projetées sur le plan formé par l’axe 1 et 3 (même 2 et 3).
barplot(res$eig[,2], col=rainbow(n=14,alpha=0.6,start=0,end=0.33),main="Pourcentage d'inertie expliquée par chaque axe", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res$eig[,2],type="b", xlim=c(0,max(res$eig[,2])+10))
text(seq(0.75,16.3,(16.3-0.75)/13),res$eig[,2]-1, paste(round(res$eig[,2],2),"%"), cex=0.7)
#text(5,22,paste(round(res$eig[,2],2)[1],"% +",round(res$eig[,2],2)[2],"% = ",round(res$eig[,2],2)[1]+round(res$eig[,2],2)[2],"%",sep=""))
On a un nouveau cercle de corrélation, ici on voit que :
plot(res, select="cos2 0.58", choix="varcor", axes = c(1,3))
On voit sur ce cercle de corrélation que les
#chisq.test(table(as.factor(data_bis$Propreté), as.factor(data_bis$Gestion.bagage)))
boxplot( data_bis$Loisir ~ data_bis$Gestion.bagage)
points(tapply(data_bis$Loisir , data_bis$Gestion.bagage ,mean), col = 'red')
boxplot( data_bis$Nourriture ~ data_bis$Siege.confort)
points(tapply(data_bis$Nourriture , data_bis$Siege.confort ,mean), col = 'red')
Les passagers sont en général plus satisfait quand ils se sont amusé (loisirs), que le service était agréable(Gestion bagage, Inflight.service, On.board.service) et qu’ils ont passé un vol confortable (Siege.confort, nourriture, propreté), et inversement pour les passagers non satisfaits.
plot(res, habillage=19, select="cos2 0.58", choix="ind", axes = c(1,3))
Ici on a le cercle de corrélation avec l’axe 2 et 3:
plot(res, select="cos2 0.6", choix="varcor", axes = c(2,3))
Il n’y a pas grand-chose à interpréter car le barycentre des voyageurs satisfaits et non satisfaits sont tout les 2 proches du centre de gravité de ce plan.
plot(res, invisible="ind",choix="ind", axes = c(2,3))
Certains passagers ont attribué comme notes 0 pour certaines catégories du vol, on décide de ne pas faire de transformation par l’inverse car \(\frac{1}{0}\) est un quotient indéterminé
On effectue la transformation ”double centrage” sur les données log-transformées afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.
data_bis2 <- log(data_bis[,c(-4:-1,-19)])
data_bis2 <- t(scale(t(data_bis2)))
res2 <- PCA(data_bis2, graph=FALSE)
## Warning in PCA(data_bis2, graph = FALSE): Missing values are imputed by the mean
## of the variable: you should use the imputePCA function of the missMDA package
barplot(res2$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.33,end=0.66),main="Pourcentage d'intertie expliquée par chaque axe\n(Données log-transformées) ", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2]-1, paste(round(res2$eig[,2],2),"%"), cex=0.7)
On effectue la transformation ”double centrage” sur les données transformées par racine carrée afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.
data_bis3 <- sqrt(data_bis[,c(-4:-1,-19)])
data_bis3 <- t(scale(t(data_bis3)))
res3 <- PCA(data_bis3, graph=FALSE)
barplot(res3$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.66,end=1),main="Pourcentage d'intertie expliquée par chaque axe\n(Données transformées par racine carrée)", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2]-1, paste(round(res3$eig[,2],2),"%"), cex=0.7)
Les transformations ne nous ont pas fait gagner plus d’informations au niveau des 2 premiers axes, on s’arrête là pour l’ACP.
Ici on a pu étudier l’impacte des variable quantitative sur la satisfaction des gens pour un trajet en avion. Il en est ressorti que les services proposés dans l’avion et le confort à bord sont des aspects primordiaux pour la satisfaction des voyageurs.
data_bis <- data[,c(1,2,4,5,23)]
paged_table(data_bis)
res.mca <-MCA(data_bis, quali.sup = 5, graph=FALSE)
D’abbord on peut observer que la première dimension influe à un peu plus de 30% quant à la 2, 3, 4 elles influent toutes autour de 20%. Il sera donc surement nécessaire de s’intéresser à ces 4 dimensions.
barplot(res.mca$eig[,2], col=rainbow(5))
par(mfrow = c(2,2))
for(i in 1:4){
barplot(res.mca$var$cos2[,i], las = 2, cex.names = 0.64,
col=rainbow(n=9,alpha=0.6,start=(i-1)/4,end=i/4),
main=paste("Cos2 des modalités pour l'axe",i))
}
En se referent aux cos2 (cos2 > 0.7) des barplots précédents :
L’axe 1 oppose les passagers qui voyagent pour le business et les passagers qui voyagent pour un motif personnel. Ceux qui voyagent pour le travail sont en général plus satisfaits et ceux qui voyagent pour un motif personnel sont en général sans avis ou insatisfaits. L’axe 2 oppose les passagers loyaux aux non loyaux, il en résulte que le passagers non loyaux sont plus souvent insatisfaits et que les passagers loyaux. Les 2 axes prennent aussi en compte a eux deux les voyageurs qui voyagent en business et en éco. On peut voir que les voyageurs en éco sont plus souvent insatisfait de leur voyage que ceux en business classe.
plot(res.mca, invisible="ind", axes=c(1,2))
En se referent aux cos2 (cos2 > 0.7) pour l’axe 3 des barplots précédents :
On peut voir que l’axe 3 oppose les personnes de sexe different, on ne peut pas dire grand-chose quant à l’influence sur la satisfaction du client, on pourrait peut-être dire que les femmes sont un peu moins satisfaites mais c’est à vérifier.
plot(res.mca, invisible="ind", axes=c(1,3))
Pour prendre en compte les voyageurs classe éco plus on visualise sur le plan formé par l’axe 3 et 4
On peut voir ici que les voyageurs en classe Éco Plus sont moins satisfaits de leur voyages, ils sont très excentrés car ils représentes des données inhabituelles.
plot(res.mca, invisible="ind", axes=c(3,4))
D’après l’ACM :
Si un passager voyage pour des raisons personnelles, il a moins de chance d’être satisfait du vol qu’un passager qui voyage pour le business.
Si le passager est un client fidèle (Loyal custommer) il a plus de chance d’être satisfait du vol qu’un passager qui est déloyal (Disloyal custommer).
Si un voyageur est en classe business, cela influera positivement sur sa satisfaction, alors que s’il est en classe Eco cela influera négativement. Les passagers Éco plus sont particuliers, mais le fait d’être en classe Éco plus influe négativement sur leur satisfaction.
Le sexe de l’individu n’a pas l’air d’influer significativement sur la satisfaction, mais on peut faire l’hypothèse que les femmes sont moins satisfaites que les hommes.
Nous allons maintenant tenter de regrouper les individus par groupes en utilisant les différentes méthodes de clusterig. Il n’y aura pas grand intérêt à les réaliser sur l’ensemble des individus, nous allons donc modifier le jeu de données afin d’analyser les données en fonction des “profils” d’individus. On pourra de cette manière déterminer quels sont les profils les plus proches en terme de notation, et de satisfaction
On définit alors plusieurs profils :
Homme - Loyal - Personnel - Eco Plus
Homme - Loyal - Personnel - Eco
Homme - Loyal - Personnel - Business
Homme - Loyal - Business - Eco Plus
Homme - Loyal - Business - Eco
Homme - Loyal - Business - Business
Homme - Non Loyal - Personnel - Eco Plus
Homme - Non Loyal - Personnel - Eco
Homme - Non Loyal - Personnel - Business
Homme - Non Loyal - Business - Eco Plus
Homme - Non Loyal - Business - Eco
Homme - Non Loyal - Business - Business
Femme - Loyal - Personnel - Eco Plus
Femme - Loyal - Personnel - Eco
Femme - Loyal - Personnel - Business
Femme - Loyal - Business - Eco Plus
Femme - Loyal - Business - Eco
Femme - Loyal - Business - Business
Femme - Non Loyal - Personnel - Eco Plus
Femme - Non Loyal - Personnel - Eco
Femme - Non Loyal - Personnel - Business
Femme - Non Loyal - Business - Eco Plus
Femme - Non Loyal - Business - Eco
Femme - Non Loyal - Business - Business
On décrit donc 24 profils possibles
data.quant <- data[,7:20]
data.quant <- cbind(data.quant, rowMeans(data.quant))
colnames(data.quant) = c(colnames(data.quant)[1:14],"Moyenne")
data.qual <- data[,c(1,2,4,5,23)]
head(data.qual)
## Genre Fidélité Type.du.vol Classe Satisfaction
## n°1 Male Loyal Customer Personal Travel Eco Plus neutral or dissatisfied
## n°2 Male disloyal Customer Business travel Business neutral or dissatisfied
## n°3 Female Loyal Customer Business travel Business satisfied
## n°4 Female Loyal Customer Business travel Business neutral or dissatisfied
## n°5 Male Loyal Customer Business travel Business satisfied
## n°6 Female Loyal Customer Personal Travel Eco neutral or dissatisfied
data_count_1 <- aggregate(data.quant[,14] ~ data.qual$Satisfaction , data, mean)
data_count_1
## data.qual$Satisfaction data.quant[, 14]
## 1 neutral or dissatisfied 2.912859
## 2 satisfied 3.726229
summary(data[,9:20])
## Facilité.resevation Emplacement.porte Nourriture Enregistrement.en.ligne
## Min. :0.000 Min. :1.000 Min. :0.000 Min. :0.000
## 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000
## Median :3.000 Median :3.000 Median :3.000 Median :3.000
## Mean :2.766 Mean :2.971 Mean :3.218 Mean :3.251
## 3rd Qu.:4.000 3rd Qu.:4.000 3rd Qu.:4.000 3rd Qu.:4.000
## Max. :5.000 Max. :5.000 Max. :5.000 Max. :5.000
## Siege.confort Loisir On.board.service Espace.jambe
## Min. :1.000 Min. :0.000 Min. :0.00 Min. :0.000
## 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.00 1st Qu.:2.000
## Median :4.000 Median :4.000 Median :4.00 Median :4.000
## Mean :3.422 Mean :3.338 Mean :3.36 Mean :3.338
## 3rd Qu.:5.000 3rd Qu.:4.000 3rd Qu.:4.00 3rd Qu.:4.000
## Max. :5.000 Max. :5.000 Max. :5.00 Max. :5.000
## Gestion.bagage Checkin.service Inflight.service Propreté
## Min. :1.000 Min. :1.000 Min. :0.000 Min. :1.000
## 1st Qu.:3.000 1st Qu.:3.000 1st Qu.:3.000 1st Qu.:2.000
## Median :4.000 Median :3.000 Median :4.000 Median :3.000
## Mean :3.622 Mean :3.318 Mean :3.653 Mean :3.267
## 3rd Qu.:5.000 3rd Qu.:4.000 3rd Qu.:5.000 3rd Qu.:4.000
## Max. :5.000 Max. :5.000 Max. :5.000 Max. :5.000
res = scale(data[1:500,9:20],center = TRUE,scale = TRUE)
d.indiv = dist(res)
#d.indiv
hc <- hclust(d.indiv)
plot(hc,cex = 0.1, col=1)
#K = 5
? hclust
## Help on topic 'hclust' was found in the following packages:
##
## Package Library
## stats /usr/lib/R/library
## flashClust /home/aissam/R/x86_64-pc-linux-gnu-library/4.0
##
##
## Using the first match ...
#rect.hclust(hc, k = K)
Nous allons à présent nous pencher sur la corrélation entre les différentes variables. En observant
data_bis = data[,7:20]
mean_notes <-rowMeans(data_bis)
data[1:20,23]
## [1] "neutral or dissatisfied" "neutral or dissatisfied"
## [3] "satisfied" "neutral or dissatisfied"
## [5] "satisfied" "neutral or dissatisfied"
## [7] "neutral or dissatisfied" "satisfied"
## [9] "neutral or dissatisfied" "neutral or dissatisfied"
## [11] "neutral or dissatisfied" "neutral or dissatisfied"
## [13] "neutral or dissatisfied" "satisfied"
## [15] "neutral or dissatisfied" "neutral or dissatisfied"
## [17] "satisfied" "satisfied"
## [19] "satisfied" "neutral or dissatisfied"
plot(mean_notes[1:20])
boxplot( data_bis$Nourriture ~ data_bis$Gestion.bagage)
points(tapply(data_bis$Nourriture, data_bis$Gestion.bagage ,mean), col = 'red')
res = lm(formula = data_bis$Wifi ~ data_bis$Propreté)
summary(res)
##
## Call:
## lm(formula = data_bis$Wifi ~ data_bis$Propreté)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.9594 -0.8337 0.1663 1.1663 2.5434
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.33092 0.04985 46.762 <2e-16 ***
## data_bis$Propreté 0.12571 0.01415 8.885 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.319 on 4998 degrees of freedom
## Multiple R-squared: 0.01555, Adjusted R-squared: 0.01535
## F-statistic: 78.94 on 1 and 4998 DF, p-value: < 2.2e-16
anova(res)
## Analysis of Variance Table
##
## Response: data_bis$Wifi
## Df Sum Sq Mean Sq F value Pr(>F)
## data_bis$Propreté 1 137.4 137.39 78.941 < 2.2e-16 ***
## Residuals 4998 8698.8 1.74
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1